package roslan.musicbox.preprocess;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class TagPreProcessor {
	char[] stops = {';',':','"','\'','(',')',' ','-'};
	private Document xmlDoc;
	private HashSet<String> genreList;
	
	public TagPreProcessor(String inputfile, String outputfile){
		System.out.println("init");
		initDom(inputfile);
		System.out.println("process");
		process(outputfile);
		System.out.println("write");
		saveToXmlFile(outputfile);
	}
	
	public void initDom(String infilename){
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try{
			DocumentBuilder db = dbf.newDocumentBuilder();
			xmlDoc = db.parse(new File(infilename));
		}catch(Exception e){
			e.printStackTrace();
		}
		
		genreList = new HashSet<String>();
		genreList.clear();
		Scanner scanner = null;
		try{
			scanner = new Scanner("genre_list.txt");
		}catch(Exception e){}
		while(scanner.hasNextLine()){
			String genre = scanner.nextLine();
			genreList.add(genre);
		}
		
	}

	private String removeBracket(String title){
		int start;
		while(title.contains("(")){
			start = title.indexOf("(");
			int end = start;
			while (end<title.length() && title.charAt(end)!=')') end++;
			if (end >= title.length()-1){
				title = title.substring(0, start);
			}
			else {
				title = title.substring(end+1);
			}
		}
		while(title.contains("[")){
			start = title.indexOf("[");
			int end = start;
			while (end<title.length() && title.charAt(end)!=']') end++;
			if (end >= title.length()-1)
				title = title.substring(0, start);
			else {
				title = title.substring(end+1);
			}
		}
		return title.trim();
	}
	
	private int indexOfWords(String s){
		int index = 0;
		char c;
		while (index<s.length()){
			c = s.charAt(index);
			if (((c<=122)&&(c>=97))||((c<=90)&&(c>=65))||c>128)
				break;
			index++;
		}
		return index;
	}
	
	private String trimTitle(String title){
		title = title.trim();
		title = title.substring(0, title.lastIndexOf('.'));
		if (title.indexOf('.')>0)
			title = title.substring(title.indexOf('.')+1);
		title = title.substring(indexOfWords(title));
		title = removeBracket(title);
		return title.trim();
	}
	
	private String trimAlbum(String album){
		album = album.trim();
		album = album.substring(indexOfWords(album));
		album = removeBracket(album);
		return album;
	}
	
	private String trimGenre(String genre){
		genre = removeBracket(genre);
		if(genreList.contains(genre)) return genre;
		else return "Pop";
	}
	
	public void process(String outputFile){
		NodeList titles = xmlDoc.getElementsByTagName("Title");
		NodeList artists = xmlDoc.getElementsByTagName("Artist");
		NodeList paths = xmlDoc.getElementsByTagName("Fullpath");
		NodeList years = xmlDoc.getElementsByTagName("Year");
		NodeList albums = xmlDoc.getElementsByTagName("Album");
		NodeList genres = xmlDoc.getElementsByTagName("Genre");
		NodeList trackNumbers = xmlDoc.getElementsByTagName("TrackNumber");
		
		for (int ii = 0; ii<titles.getLength(); ii++){
			if (ii%100 == 0)
				System.out.println(ii);
			String path = paths.item(ii).getTextContent();
			String year = years.item(ii).getTextContent();
			String genre = genres.item(ii).getTextContent();
			int i1 = 0;
			{
				if (path.contains("Female"))
					i1 = path.indexOf("Female")+7;
				else if (path.contains("Male"))
					i1 = path.indexOf("Male")+5;
				else if (path.contains("Band_Group"))
					i1 = path.indexOf("Band_Group")+11;
			}
			String[] info = path.substring(i1).split("/");
			String artist = info[0];
			String album = albums.item(ii).getTextContent();
			if(info.length > 1) album = info[1];
			String title = titles.item(ii).getTextContent();
			if(info.length > 1) title = info[info.length-1];
			String column = "";
			//extract year from album, trim the title
			{
				boolean hasyear = true;
				for (int i = 0; i<4; i++){
					if (album.length()<=i){
						hasyear = false;
						break;
					}
					char c = album.charAt(i);
					if (c>'9' || c<'0'){
						hasyear = false;
						break;
					}
				}
				if (hasyear){
					year = album.substring(0,4);
				}
				
			}
			//extract column from title
			{
				boolean hascolumn = true;
				for (int i = 0; i<2; i++){
					if (title.length()<=i){
						hascolumn = false;
						break;
					}
					char c = title.charAt(i);
					if (c>'9' || c<'0'){
						hascolumn = false;
						break;
					}
				}
				if (hascolumn)
					column = title.substring(0,2);
			}
			titles.item(ii).setTextContent(trimTitle(title));
			artists.item(ii).setTextContent(artist);
			albums.item(ii).setTextContent(trimAlbum(album));
			years.item(ii).setTextContent(year);
			genres.item(ii).setTextContent(trimGenre(genre));
			trackNumbers.item(ii).setTextContent(column);
		}
	}
	
	public static String miningPath(String path){
		int i1 = 0;
		if (path.contains("Female"))
			i1 = path.indexOf("Female")+7;
		else if (path.contains("Male"))
			i1 = path.indexOf("Male")+5;
		else if (path.contains("Band_Group"))
			i1 = path.indexOf("Band_Group")+11;
		String[] info = path.substring(i1).split("/");
		String artist = info[0];
		String album = info[info.length-2];
		String title = info[info.length-1];
		String year = "";
		String column = "";
		//extract year from album, trim the title
		{
			boolean hasyear = true;
			for (int i = 0; i<4; i++){
				if (album.length()<=i){
					hasyear = false;
					break;
				}
				char c = album.charAt(i);
				if (c>'9' || c<'0'){
					hasyear = false;
					break;
				}
			}
			if (hasyear)
				year = album.substring(0,4);
			
		}
		//extract column from title
		{
			boolean hascolumn = true;
			for (int i = 0; i<2; i++){
				if (title.length()<=i){
					hascolumn = false;
					break;
				}
				char c = title.charAt(i);
				if (c>'9' || c<'0'){
					hascolumn = false;
					break;
				}
			}
			if (hascolumn)
				column = title.substring(0,2);
		}
		System.out.println(artist+"\t"+album+"\t"+year+"\t"+column+"\t"+title);
		return null;
	}
	
	public void saveToXmlFile(String filename){
		try{
			Transformer t = TransformerFactory.newInstance().newTransformer();
			t.setOutputProperty("indent", "yes");
			t.transform(new DOMSource(xmlDoc), new StreamResult(new File(filename)));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws IOException{
		for(int i=2;i<10;++i){
			String filename = "test/tagdb."+i+".xml";
			new TagPreProcessor(filename,filename);
		}
	}
	
}
